package com.yuma.rabbitmq.reliability3consumer.listener;


import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Slf4j
@Component
public class Consumer {

    @RabbitListener(queues = "queue0")
    public void receive(String msg, Message message, Channel channel) throws IOException {
        // 获取当前消息的唯一标识
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        log.info("deliveryTag: {}", deliveryTag);
        log.info("消息：{}",msg);

        try {

            // 核心操作
            log.info("消费端接收到消息：{}", msg);
            // 核心操作成功,返回 ACK 信息
            // deliveryTag: 消息的唯一标识,64 位的长整型,消息往消费端投递时,会分配一个唯一的 deliveryTag 值
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            // 获取当前消息是否是重复投递的,true 说明当前消息已经重试过一次了, false 说明当前消息是第一次投递
            Boolean redelivered = message.getMessageProperties().getRedelivered();

            // 核心操作失败,返回 NACK 信息
            // 第一个参数： 应答/拒绝应答那一条消息
            // 第二个参数：multiple deliveryTag之后的消息否批量应答,true 表示批量应答, false 表示单条应答
            // 第三个参数 requeue: 是否重新入队,true 表示重新入队, false 表示丢弃
            if (redelivered){
                // 如果当前消息已经是重复投递的,则说明此前已经重试过一次了,则不再重试过了,直接丢弃
                channel.basicNack(deliveryTag, false, false);
            }else {
                // 如果当前消息不是重复投递的,则说明此前没有重试过一次,则重试过一次,重新入队
                channel.basicReject(deliveryTag, true);
            }

            throw new RuntimeException(e);
        }
    }
}
